#ifndef AVIATION_UTIL_H
#define AVIATION_UTIL_H

#include <vector>
#include <string>
#include <sstream>

#include <boost/functional/hash.hpp>

namespace aviation
{
namespace util
{

/// Formats any integral type into a String.
/// \param x The object to be formatted.
/// \param minSize The minimum size of the returned string.
/// \param fillChar The character to pad the returned string with, if its size does not meet the minimum.
/// \returns The type X, formatted as a string.+
template <typename T>
std::string XtoA(const T& x, unsigned minSize = 0, char fillChar = ' ')
{
	std::stringstream stream;
	stream.width(minSize);
	stream.fill(fillChar);
	stream << x;
	return stream.str();
}

/// Hash a string.
/// \param string The string to be hashed.
/// \returns The string, hashed into an integer.
/// We explicitly don't worry about hash collisions.
/// This is obviously a huge drawback!!
/// With a database this small the chances of collisions are very small, so we cross our fingers
/// and hope not to encounter any super nasty bugs.
inline const unsigned HashString(const std::string& string)
{
	boost::hash<std::string> stringHash;
	return stringHash(string);
}

/// Tokenises a string into a vector of substrings.
/// \param s The string to be tokenised.
/// \returns The individual words in the string, separated into a vector.
inline const std::vector<std::string> TokeniseString(const std::string& s)
{
	std::stringstream stringStream(s);
	std::string token;
	std::vector<std::string> tokenContainer;

	while(getline(stringStream, token, ' '))
	{
		if(token != "") tokenContainer.push_back(token);
		token.clear();
	}
	return tokenContainer;
}

/// Searches for matches in two vectors of substrings.
/// \param strings The strings to be searched IN.
/// \param subStrings The strings to be searched WITH.
/// \returns True if any of subStrings are found in strings. Note that this is not commutative.
inline const bool SearchForSubstringMatchesInStrings(const std::vector<std::string> strings, const std::vector<std::string> subStrings)
{
	for(auto i1 = subStrings.begin(); i1 != subStrings.end(); ++i1)
	{
		bool foundMatch = false;

		for(auto i2 = strings.begin(); i2 != strings.end(); ++i2)
			foundMatch = (i2->find(*i1) != i2->npos) ? true : foundMatch;

		if(!foundMatch) return false;
	}
	return true;
}

}
}

#endif // AVIATION_UTIL_H